package org.inspursc.s0517.health.evaluation.service.impl;

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.inspursc.s0517.health.common.dto.SysUserDTO;
import org.inspursc.s0517.health.common.entity.SysUser;
import org.inspursc.s0517.health.common.enums.UserTypeEnum;
import org.inspursc.s0517.health.common.service.SysUserService;
import org.inspursc.s0517.health.common.util.SpringSecurityUtils;
import org.inspursc.s0517.health.common.vo.SysUserVO;
import org.inspursc.s0517.health.evaluation.converter.CustomerConverter;
import org.inspursc.s0517.health.evaluation.dao.CustomerDao;
import org.inspursc.s0517.health.evaluation.dto.*;
import org.inspursc.s0517.health.evaluation.entity.Customer;
import org.inspursc.s0517.health.evaluation.service.CustomerService;
import org.inspursc.s0517.health.evaluation.service.SurveyAnswerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.*;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author B_Dream
 * @date 2018/5/22 11:06
 */
@Service
@Slf4j
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    private CustomerDao customerDao;

    @Autowired
    private SurveyAnswerService answerService;

    @Autowired
    private SysUserService sysUserService;

    @Override
    public List<CustomerDTO> findAll() {
        Sort sort = new Sort(Sort.Direction.DESC,"id");
        List<Customer> customers = customerDao.findAll(sort);
        List<CustomerDTO> dtos = customers.stream().map(CustomerConverter::converter).collect(Collectors.toList());
        return dtos;

    }

    private CustomerToListDTO getListByCondition(FindConditionDTO conditionDTO) {


        String name = conditionDTO.getName();
        String phone = conditionDTO.getPhone();
        String sex = conditionDTO.getSex();
        String idNumber = conditionDTO.getIdNumber();
        Integer organizationId = conditionDTO.getOrganizationId();
        Integer appraiserId = conditionDTO.getAppraiserId();


        Specification<Customer> specification = new Specification<Customer>() {


            @Override
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();

                if (name != null && !"".equals(name)) {
                    Predicate preName = criteriaBuilder.like(root.get("name"), "%" + name + "%");
                    predicates.add(preName);
                }
                if (phone != null && !"".equals(phone)) {
                    Predicate prePhone = criteriaBuilder.like(root.get("phone"), "%" + phone + "%");
                    predicates.add(prePhone);
                }
                if (sex != null && !"".equals(sex)) {
                    Predicate preSex = criteriaBuilder.like(root.get("sex"), "%" + sex + "%");
                    predicates.add(preSex);
                }
                if (idNumber != null && !"".equals(idNumber)) {
                    Predicate preidNumber = criteriaBuilder.like(root.get("idNumber"), "%" + idNumber + "%");
                    predicates.add(preidNumber);
                }
                if (appraiserId != null) {
                    Predicate predicateApp = criteriaBuilder.equal(root.get("appraiserId"), appraiserId);
                    predicates.add(predicateApp);
                }
                if (organizationId != null) {
                    Predicate predicateOrg = criteriaBuilder.equal(root.get("organizationId"), organizationId);
                    predicates.add(predicateOrg);
                }

                Predicate[] p = new Predicate[predicates.size()];
                return criteriaBuilder.and(predicates
                        .toArray(p));
            }
        };
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageable = new PageRequest(conditionDTO.getPageNum() - 1, conditionDTO.getPageSize(), sort);
        Page<Customer> customers = customerDao.findAll(specification, pageable);

        Iterator iterator = customers.iterator();
        List<Customer> custs = new ArrayList<>();
        while (iterator.hasNext()) {
            custs.add((Customer) iterator.next());
        }

        List<CustomerDTO> dtos = custs.stream().map(CustomerConverter::converter).collect(Collectors.toList());
        for (CustomerDTO dto : dtos) {
            List<SurveyAnswerDTO> answers = answerService.findAllByPersonnel(dto.getId());
            List<AssessmentNumDTO> nums = new ArrayList<>();
            for (SurveyAnswerDTO answer : answers) {
                AssessmentNumDTO numDTO = new AssessmentNumDTO();
                numDTO.setSuName(answer.getSurveyName());
                numDTO.setSuId(answer.getSurveyId());
                numDTO.setSuAnswerId(answer.getId());
                numDTO.setDateTime(getNowDateShort(answer.getDateTime()));

                nums.add(numDTO);
            }
            dto.setAssessment(nums);
        }
        CustomerToListDTO customerList = new CustomerToListDTO();
        customerList.setPageNum(conditionDTO.getPageNum());
        customerList.setPageSize(conditionDTO.getPageSize());
        customerList.setTotal(customers.getTotalElements());
        customerList.setPersonnel(dtos);
        return customerList;

    }

    public String getNowDateShort(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd");
        String dateString = formatter.format(date);
        return dateString;
    }


    @Override
    public CustomerToListDTO finCustomerListByCondition(FindConditionDTO conditionDTO, HttpServletRequest request) {

        SysUser sysUser = SpringSecurityUtils.getCurrentUser(request);
        String userType;

        if (sysUser != null) {
            userType = sysUser.getUserType();
            if (!StringUtils.isEmpty(userType)) {
                if (userType.equals(UserTypeEnum.ORGADMIN.getCode())) {
                    conditionDTO.setOrganizationId(sysUser.getOrganizationId());
                    return getListByCondition(conditionDTO);
                } else if (userType.equals(UserTypeEnum.APPRAISER.getCode())) {
                    conditionDTO.setOrganizationId(sysUser.getOrganizationId());
                    conditionDTO.setAppraiserId(sysUser.getId());
                    return getListByCondition(conditionDTO);
                } else if (userType.equals(UserTypeEnum.ADMIN.getCode())) {
                    return getListByCondition(conditionDTO);
                } else {
                    log.error("异常用户登录！");
                    return null;
                }
            } else {
                log.error("用户：" + sysUser.getUsername() + sysUser.getId() + "未设置用户类型！");
                return null;
            }

        } else {
            return null;
        }


    }


    @Override
    public CustomerDTO findByIdNumber(String idNumber) {
        Customer customer = customerDao.findByIdNumber(idNumber);
        if (customer != null) {
            CustomerDTO dto = CustomerConverter.converter(customer);
            return dto;
        } else {
            return null;
        }
    }


    @Override
    public CustomerDTO findById(Integer id) {
        CustomerDTO dto = CustomerConverter.converter(customerDao.getOne(id));
        return dto;
    }

    @Override
    public List<CustomerDTO> findByBelongId(Integer belongId) {
        List<Customer> customers = customerDao.findAllByOrganizationId(belongId);
        List<CustomerDTO> dtos = customers.stream().map(CustomerConverter::converter).collect(Collectors.toList());
        return dtos;
    }


    @Override
    public List<CustomerDTO> findAllByAppraiserId(Integer appId) {
        List<Customer> customers = customerDao.findAllByAppraiserId(appId);
        List<CustomerDTO> dtos = customers.stream().map(CustomerConverter::converter).collect(Collectors.toList());
        return dtos;
    }

    @Override
    public Boolean deleteById(Integer id, HttpServletRequest request) throws Exception{


        SysUser user = SpringSecurityUtils.getCurrentUser(request);
        //判断权限是否为系统管理员
        //如果不是
        if ( UserTypeEnum.ADMIN.getCode().equals(user.getUserType())) {
            try {
                customerDao.deleteById(id);
                return true;
            } catch (Exception e) {
                log.error("【删除失败】", e.getMessage());
                return false;
            }
        } else {
            throw new Exception("暂时只允许系统管理员删除客户");
        }
    }

    @Override
    public Boolean deleteByIdNumber(String idNumber, HttpServletRequest request) throws Exception {
        SysUser user = SpringSecurityUtils.getCurrentUser(request);
        //判断权限是否为系统管理员
        //如果不是
        if ( UserTypeEnum.ADMIN.getCode().equals(user.getUserType())) {
            try {
                customerDao.deleteCustomerByIdNumber(idNumber);
                return true;
            } catch (Exception e) {
                log.error("【删除失败】", e.getMessage());
                return false;
            }
        } else {
            throw new Exception("暂时只允许系统管理员删除客户");
        }
    }


    @Override
    public CustomerDTO save(CustomerDTO customer, HttpServletRequest request) throws Exception {
        SysUser sysUser = SpringSecurityUtils.getCurrentUser(request);
        if (sysUser != null && sysUser.getId() != null && sysUser.getOrganizationId() != null) {
            customer.setAppraiserId(sysUser.getId());
            customer.setOrganizationId(sysUser.getOrganizationId());
        } else {
            throw new Exception("数据异常！");
        }
        try {
            Customer cust = CustomerConverter.converter(customer);
            Customer newCustomer = customerDao.saveAndFlush(cust);
            CustomerDTO newcust = CustomerConverter.converter(newCustomer);
            return newcust;
        } catch (Exception e) {
            String msg = e.getMessage();
            if (msg.contains("could not execute statement") && msg.contains("constraint [id_number]")){
                CustomerDTO existCustomer = findByIdNumber(customer.getIdNumber());
                SysUserVO creatorUser = sysUserService.findById(existCustomer.getAppraiserId());
                throw new Exception("输入的<span class='red'>身份证号在系统中已经存在</span>！<br/>已存在客户信息：<span class='red'>身份证：" + existCustomer.getIdNumber() + "</span>, 姓名：" + existCustomer.getName() + "；<br/>创建者：" + creatorUser.getUsername());
            }
            throw new Exception("数据转换/保存时异常！");
        }
    }


    @Override
    public Map<String, Integer> getAgeRangeCharts(HttpServletRequest request) {

        SysUser user = SpringSecurityUtils.getCurrentUser(request);
        Map<String, Integer> map = Maps.newHashMap();
        if (user.getUserType().equals(UserTypeEnum.ADMIN.getCode())) {
            List<Customer> count1 = customerDao.findByAgeBetween(0, 60);
            map.put("60以下", count1.size());
            List<Customer> count2 = customerDao.findByAgeBetween(61, 70);
            map.put("61-70", count2.size());
            List<Customer> count3 = customerDao.findByAgeBetween(71, 80);
            map.put("71-80", count3.size());
            List<Customer> count4 = customerDao.findByAgeBetween(81, 90);
            map.put("81-90", count4.size());
            List<Customer> count5 = customerDao.findByAgeBetween(91, 200);
            map.put("91以上", count5.size());
        }
        else {
//            Map<String, Long> mapAge = Maps.newHashMap();
//            List<Long> ageNums = customerDao.getCharts();
//            Object object = ageNums.get(0);

            Integer orgId = user.getOrganizationId();
            List<Customer> count1 = customerDao.findByAgeBetweenAndOrganizationId(0, 60, orgId);
            map.put("60以下", count1.size());
            List<Customer> count2 = customerDao.findByAgeBetweenAndOrganizationId(61, 70, orgId);
            map.put("61-70", count2.size());
            List<Customer> count3 = customerDao.findByAgeBetweenAndOrganizationId(71, 80, orgId);
            map.put("71-80", count3.size());
            List<Customer> count4 = customerDao.findByAgeBetweenAndOrganizationId(81, 90, orgId);
            map.put("81-90", count4.size());
            List<Customer> count5 = customerDao.findByAgeBetweenAndOrganizationId(91, 200, orgId);
            map.put("91以上", count5.size());
        }
        return map;
    }
}
